package com.mcgrobot.plugin.execute.strategy;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.mcgrobot.common.Constants;
import com.mcgrobot.common.sysenum.EletypeEnum;
import com.mcgrobot.common.sysenum.LogOutTypeEnum;
import com.mcgrobot.common.sysenum.LogTypeEnum;
import com.mcgrobot.common.sysenum.MessageTypeEnum;
import com.mcgrobot.entity.flow.httplogin.FlowHttpLogin;
import com.mcgrobot.entity.generate.ExecuteStruct;
import com.mcgrobot.entity.generate.RunResult;
import com.mcgrobot.entity.message.FlowBody;
import com.mcgrobot.entity.message.Message;
import com.mcgrobot.plugin.build.McgProduct;
import com.mcgrobot.plugin.execute.ProcessStrategy;
import com.mcgrobot.plugin.websocket.MessagePlugin;
import com.mcgrobot.util.DataConverter;

public class FlowHttpLoginStrategy implements ProcessStrategy {

	private static Logger logger = LoggerFactory.getLogger(FlowHttpLoginStrategy.class);
	
	@Override
	public void prepare(ArrayList<String> sequence, McgProduct mcgProduct, ExecuteStruct executeStruct)
			throws Exception {
		FlowHttpLogin flowHttpLogin = (FlowHttpLogin)mcgProduct;
		executeStruct.getRunStatus().setExecuteId(flowHttpLogin.getId());
	}

	@Override
	public RunResult run(McgProduct mcgProduct, ExecuteStruct executeStruct) throws Exception {
		FlowHttpLogin flowHttpLogin = (FlowHttpLogin)mcgProduct;
		JSON parentParam = DataConverter.getParentRunResult(flowHttpLogin.getId(), executeStruct);
        Message message = MessagePlugin.getMessage();
        message.getHeader().setMesType(MessageTypeEnum.FLOW);		
        FlowBody flowBody = new FlowBody();
        flowBody.setSubFlag(executeStruct.getSubFlag());
        flowBody.setFlowId(flowHttpLogin.getFlowId());
        flowBody.setOrderNum(flowHttpLogin.getOrderNum());
        flowBody.setLogOutType(LogOutTypeEnum.PARAM.getValue());
        flowBody.setEleType(EletypeEnum.JSON.getValue());
        flowBody.setEleTypeDesc(EletypeEnum.JSON.getName() + "--》" + flowHttpLogin.getHttpLoginProperty().getName());
        flowBody.setEleId(flowHttpLogin.getId());
        flowBody.setComment("参数");
        if(parentParam == null) {
        	flowBody.setContent("{}");
        } else {
        	flowBody.setContent(JSON.toJSONString(parentParam, true));
        }
        flowBody.setLogType(LogTypeEnum.INFO.getValue());
        flowBody.setLogTypeDesc(LogTypeEnum.INFO.getName());
        message.setBody(flowBody);
        MessagePlugin.push(flowHttpLogin.getMcgWebScoketCode(), executeStruct.getSession().getId(), message);		
		
        flowHttpLogin = DataConverter.flowOjbectRepalceGlobal(DataConverter.addFlowStartRunResult(parentParam, executeStruct), flowHttpLogin);		
		RunResult runResult = new RunResult();
		runResult.setElementId(flowHttpLogin.getId());
		
        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
        CloseableHttpClient closeableHttpClient = httpClientBuilder.build();
		RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(30000).setConnectTimeout(30000).build();
		Map<String, String> datas = getLoginHtml(flowHttpLogin, closeableHttpClient);
		refreshCode(flowHttpLogin, requestConfig, closeableHttpClient, datas);
		
		String codeImgUrl = "http://erp.dmall.com/getVerifyCodeImg?loginBatchNum=" + datas.get("loginBatchNum") + "&d=" + System.currentTimeMillis();
		getCode(codeImgUrl, Constants.FS_PATH + "/tmp/" + UUID.randomUUID(), closeableHttpClient);
		
		JSONObject runResultJson = (JSONObject)parentParam;
		Map<String, String> map = new HashMap<>();
		map.put("desc", flowHttpLogin.getHttpLoginProperty().getDesc());
		runResultJson.put(flowHttpLogin.getHttpLoginProperty().getKey(), map);
		runResult.setJsonVar(JSON.toJSONString(runResultJson, true));
		executeStruct.getRunStatus().setCode("success");

		logger.debug("登录控件：{}，执行完毕！执行状态：{}", JSON.toJSONString(flowHttpLogin), JSON.toJSONString(executeStruct.getRunStatus()));
		return runResult;
	}
	
    public Map<String, String> getLoginHtml(FlowHttpLogin flowHttpLogin, CloseableHttpClient closeableHttpClient) {
        HttpPost httpPost = new HttpPost(flowHttpLogin.getHttpLoginProperty().getUrl());  
        // 设置请求和传输超时时间  
        RequestConfig requestConfig = RequestConfig.custom()  
                .setSocketTimeout(30000)  
                .setConnectTimeout(30000).build();  
        httpPost.setConfig(requestConfig);  
        Map<String, String> datas = new HashMap<>();
        try {
	        CloseableHttpResponse loginResponse = closeableHttpClient.execute(httpPost);  
	        int statusCode = loginResponse.getStatusLine().getStatusCode();  
	        if(statusCode == 200) {
	        	String retStr = EntityUtils.toString(loginResponse.getEntity(), "UTF-8");
	            Document d1 = Jsoup.parse(retStr);// 转换为Dom树
	            List<Element> et = d1.select("#user-login-form");// 获取form表单，可以通过查看页面源码代码得知
	            
	            for (Element e : et.get(0).getAllElements()) {
	                if (e.attr("name").equals("account")) {
	                    e.attr("value", flowHttpLogin.getHttpLoginProperty().getUserName());// 设置用户名
	                }
	                if (e.attr("name").equals("pwd")) {
	                    e.attr("value", flowHttpLogin.getHttpLoginProperty().getUserPwd()); // 设置用户密码
	                }
	                if (e.attr("name").length() > 0) {// 排除空值表单属性
	                    datas.put(e.attr("name"), e.attr("value"));
	                }
	            }
	        }
	        return datas;
        } catch (Exception e) {
			e.printStackTrace();
		}
        return null;
    }
    
    public static String refreshCode(FlowHttpLogin flowHttpLogin, RequestConfig requestConfig, CloseableHttpClient closeableHttpClient, Map<String, String> datas) {
    	HttpPost httpPost = new HttpPost("http://erp.dmall.com/refreshVerifyCode?loginBatchNum=" + datas.get("loginBatchNum"));  
        httpPost.setConfig(requestConfig);  
        try {
	        CloseableHttpResponse operationResponse = closeableHttpClient.execute(httpPost);  
	        int statusCode = operationResponse.getStatusLine().getStatusCode();
	        if(statusCode == 200) {
	        	return EntityUtils.toString(operationResponse.getEntity(), "UTF-8");  
	        }
        } catch (Exception e) {
			e.printStackTrace();
		}
        
        return null;
    }
    
	public static String getCode(String url, String filePathName, CloseableHttpClient closeableHttpClient) {
		String code = null;
		try {
			HttpGet httpget = new HttpGet(url);

			// 伪装成google的爬虫JAVA问题查询
		//	httpget.setHeader("User-Agent", "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)");
			HttpResponse response = closeableHttpClient.execute(httpget);

			File storeFile = new File(filePathName);
			FileOutputStream output = new FileOutputStream(storeFile);

			// 得到网络资源的字节数组,并写入文件
			HttpEntity entity = response.getEntity();
			if (entity != null) {
				InputStream instream = entity.getContent();
				try {
					byte b[] = new byte[1024];
					int j = 0;
					while ((j = instream.read(b)) != -1) {
						output.write(b, 0, j);
					}
					output.flush();
					output.close();
				} catch (IOException ex) {
					throw ex;
				} catch (RuntimeException ex) {
					httpget.abort();
					throw ex;
				} finally {
					try {
						instream.close();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
			
        //    code = Tess4JTest.getCode(tempPath);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return code;
	}
}
